<template>
  <div class="v-table-td-subject">
    <DropdownCustom ref="dpcRef"
                    class="v-table-td-subject-dpc"
                    equalWidth
                    v-if="editing"
                    :toggleIcon="false"
                    trigger="manual">
    <textarea
        ref="textareaRef"
        placeholder="请输入科目名称/科目编码/科目名称拼音首字母快速搜索"
        v-model="subjectVal"
        @input="onSubjectValChange"
        @blur="canEditing&&endEdit()"
        @keydown.enter.prevent="onEnter"
        @keydown="onKeyDownKey"
        @keyup.up.prevent="moveSelect(-1)"
        @keyup.down.prevent="moveSelect(1)"
        class="v-table-td-subject-edit"
    ></textarea>
      <template #content>
        <div ref="subjectListRef" class="v-table-td-subject-list" @mouseenter="canEditing=false" @mouseleave="onMouseleave">
          <div class="v-table-td-subject-list-content">
            <ul ref="subjectUlRef">
              <li :class="{'subject-selected':filterVal===s.code}" @click="selectSubject" :data-code="s.code"
                  :data-id="s.id" v-for="s in subjectListFilter" :key="s.code">{{ s.code }} {{ s.fullName }}
              </li>
            </ul>
          </div>
        </div>
      </template>
    </DropdownCustom>
    <div v-else class="p-8px h-full v-table-td-subject-text" @click="doEdit">
      <template v-if="subjectObj">
        {{ subjectObj.code }} {{ subjectObj.fullName }}
        <template v-if="auxiliary">
          <span v-for="ax in auxiliary">{{ ax?.code }}-{{ ax?.name }}</span>
        </template>
        <div class="addon" @click.stop="void(0)" v-if="hasAuxiliary">
          <Tooltip content="辅助项">
            <i @click="setAuxiliary" class="fa  fa-vcard text-hover"></i>
          </Tooltip>
        </div>
      </template>
    </div>
    <div v-if="subjectObj" class="v-table-td-subject-balance" :class="balance<0?'red-color':''">
      余额：{{ balance ? numFormat(balance) : 0 }}
    </div>
    <div @click.stop="void(0)" v-if="subjectObj && (subjectObj.unit || hasCurrency)" class="v-table-td-subject-unit-currency">
      <div v-if="subjectObj.unit" class="text-hover">
        <DropdownCustom :toggleIcon="false" ref="unitDp" @show="numDpShow">
          数量：{{ detail.num || 0 }} {{ subjectObj.unit }}，单价：{{ detail.price || 0 }}
          <template #content>
            <div class="p-8px">
              <span>数量：</span>
              <vxe-input type="float" digits="5" ref="numRef" style="flex: inherit;width: 100px" autofocus @change="numChange" v-model.number="detail.num" placeholder="请输入数量"/>
              <span style="margin-left: 5px;">{{ subjectObj.unit }}，单价：</span>
              <vxe-input @keydown="numTabBlur" @blur="numBlur" ref="priceRef" type="float" style="flex: inherit;width: 100px" @change="numChange" v-model.number="detail.price" placeholder="请输入单价"/>
            </div>
          </template>
        </DropdownCustom>
      </div>
      <!--      <div class="mt-5px text-hover" v-if="hasCurrency">-->
      <!--        币别：3 ，汇率：13，原币：1-->
      <!--      </div>-->
    </div>
  </div>
</template>
<script setup>
import {computed, h, inject, nextTick, ref, watch} from "vue";
import {useStore} from "vuex";
import {scrollIntoView} from "heyui.ext";
import VTableAuxiliary from "@components/common/VoucherTable/VTableAuxiliary.vue";
import {layer} from "@layui/layer-vue";
import {multiply, pick, round} from "xe-utils";

const props = defineProps(['subject', 'rowIndex', 'subjectList', 'subjectMap', 'auxiliary', 'detail']);
const store = useStore();

const detail = inject('detail');
const dpcRef = ref(null)
const textareaRef = ref(null)
const tabsRef = ref(null)
const subjectUlRef = ref(null)

const editing = ref(false)
const canEditing = ref(true)
const subjectVal = ref("")
const filterVal = ref(null)
const unitDp = ref(null)
const numRef = ref(null)
const priceRef = ref(null)
const subjectType = ref("全部")
const subjectObj = ref(null)

const updateFiled = inject('updateFiled');
const next = inject('next');
const loadSubject = inject('loadSubject');
const loadSubjectBalance = inject('loadSubjectBalance');
const subjectBalance = inject('subjectBalance');
const updateSubjectBalance = inject('updateSubjectBalance');
const balance = computed(() => {
  return subjectBalance.value[subjectObj.value.id] || 0;
});

watch(() => props.subject, (val) => {
  subjectObj.value = val;
  if (val) {
    subjectVal.value = val.code + " " + val.fullName;
  } else {
    subjectVal.value = "";
  }
}, {immediate: true})

watch(() => [props.detail.debitAmount, props.detail.creditAmount], () => {
  subjectObj.value && updateSubjectBalance(subjectObj.value)
});

watch(subjectObj, (subject) => {
  subject && loadSubjectBalance(subject, props.detail.currencyId, (props.auxiliary || []).map(val => pick(val, ['id', 'categoryType', 'categoryId'])))
})

/**
 * 是否带辅助
 * @type {ComputedRef<boolean>}
 */
const hasAuxiliary = computed(() => {
  return subjectObj.value && subjectObj.value.auxiliaryAccounting && subjectObj.value.auxiliaryAccounting.length;
})

/**
 * 是否带外币
 * @type {ComputedRef<boolean>}
 */
const hasCurrency = computed(() => {
  return subjectObj.value && subjectObj.value.currencyAccounting && subjectObj.value.currencyAccounting.length;
})

function filter(val) {
  if (filterVal.value) {
    return (val.code.indexOf(filterVal.value) !== -1 ||
        val.fullName.indexOf(filterVal.value) !== -1 ||
        val.mnemonicCode.indexOf(filterVal.value) !== -1);
  }
  return true;
}

/**
 * 科目过滤
 * @type {ComputedRef<unknown>}
 */
const subjectListFilter = computed(() => {
  if (subjectType.value === '全部') {
    if (filterVal.value) {
      return props.subjectList.filter(val => filter(val));
    }
    return props.subjectList;
  }
  return props.subjectList.filter(val => val.type === subjectType.value && filter(val));
})

/**
 * 开启科目编辑
 */
const doEdit = () => {
  editing.value = true;

  nextTick(() => {
    setTimeout(() => {
      dpcRef.value.show();
      nextTick(() => {
        textareaRef.value.focus();
        textareaRef.value.select();
      })
    }, 10);
  })
}

/**
 * 科目输入过滤值
 * @param e
 */
const onSubjectValChange = (e) => {
  filterVal.value = e.target.value;
  nextTick(() => {
    moveSelect()
  })
}

/**
 * 结束编辑
 * @returns {boolean}
 */
const endEdit = () => {
  if (!editing.value) {
    return true;
  }
  editing.value = false;
  subjectType.value = '全部'
  filterVal.value = null
  dpcRef.value && dpcRef.value.hide();
  if (hasAuxiliary.value && (!props.auxiliary || !props.auxiliary.length)) {
    setAuxiliary();
    return false;
  }
  if (subjectObj.value && subjectObj.value.unit) {
    setTimeout(() => {
      unitDp.value.show();
      nextTick(() => {
        numRef.value.focus();
        numRef.value.select();
      })
    }, 300)
    return false;
  }
  return true;
}

const numBlur = ({value, $event}) => {
  $event.preventDefault();
  unitDp.value.hide();
  nextTick(() => {
    next(props.rowIndex, subjectObj.value.balanceDirection === '贷' ? 'creditAmount' : 'debitAmount');
  })
}

const numTabBlur = ({value, $event}) => {
  if ($event.key === 'Tab') {
    $event.preventDefault();
    unitDp.value.hide();
    nextTick(() => {
      next(props.rowIndex, subjectObj.value.balanceDirection === '贷' ? 'creditAmount' : 'debitAmount');
    })
  }
}

const numDpShow = () => {
  nextTick(() => {
    numRef.value.focus();
    numRef.value.select();
  })
}

const onKeyDownKey = (e) => {
  switch (e.key) {
    case 'Tab':
      e.preventDefault();
      onEnter();
      break
  }
}

/**
 * 回车和Tab键操作
 */
const onEnter = () => {
  let selector = subjectUlRef.value.querySelector('.subject-selected');
  setValueAndGoNext(selector)
}

/**
 * 鼠标选择科目
 * @param e
 */
const selectSubject = (e) => {
  setValueAndGoNext(e.target)
}

/**
 * 赋值选择科目
 * @param selector
 */
const setValueAndGoNext = (selector) => {
  let nextField = 'debitAmount';
  if (selector) {
    let newSubject = props.subjectMap[selector.dataset.id];
    if (subjectObj.value && newSubject.id !== subjectObj.value.id) {
      //修改了科目清除已选择的辅助项目
      updateFiled(props.rowIndex, 'auxiliary', []);
    }

    subjectObj.value = newSubject;
    updateFiled(props.rowIndex, 'subject', subjectObj.value);

    subjectVal.value = subjectObj.value.subjectCode + " " + subjectObj.value.subjectName;
    if (subjectObj.value.balanceDirection === '贷') {
      nextField = 'creditAmount';
    }
  }
  if (endEdit()) {
    next(props.rowIndex, nextField);
  }
}

/**
 * 鼠标移出科目选择区域
 */
const onMouseleave = () => {
  canEditing.value = true;
  textareaRef.value.focus();
}

/**
 * 切换科目分类过滤
 * @param step
 */
const moveTab = (step) => {
  let selector = tabsRef.value.querySelector('.selected');
  let sibling;
  if (step > 0) {
    sibling = selector.nextElementSibling
  } else {
    sibling = selector.previousElementSibling
  }

  if (sibling) {
    subjectType.value = sibling.innerText.trim();
    sibling.classList.add('selected')
    selector.classList.remove('selected')
  }
}

/**
 * 科目选择键盘方向键控制
 * @param step
 */
const moveSelect = (step) => {
  let selector = subjectUlRef.value.querySelector('.subject-selected');
  let sibling;

  if (selector) {
    if (step > 0) {
      sibling = selector.nextElementSibling
    } else {
      sibling = selector.previousElementSibling
    }
    if (sibling) {
      sibling.classList.add('subject-selected')
      selector.classList.remove('subject-selected')
      scrollIntoView(sibling, {
        time: 500, // 动画时间
      })
    }
  } else {
    sibling = subjectUlRef.value.children[0];
    sibling && sibling.classList.add('subject-selected');
  }
}

/**
 * 设置科目辅助项目
 */
const setAuxiliary = () => {
  let layerId = layer.open({
    title: subjectObj.value.code + " " + subjectObj.value.fullName,
    shadeClose: false,
    closeBtn: false,
    zIndex: 1000,
    area: ['400px', '300px'],
    content: h(VTableAuxiliary, {
      subject: subjectObj.value,
      auxiliary: props.auxiliary,
      detail: detail,
      onClose: () => {
        layer.close(layerId);
      },
      onSuccess: (auxiliary) => {
        updateFiled(props.rowIndex, 'auxiliary', auxiliary || []);
        layer.close(layerId);
        next(props.rowIndex, subjectObj.value.balanceDirection === '贷' ? 'creditAmount' : 'debitAmount');
        loadSubjectBalance(subjectObj.value, props.detail.currencyId, (auxiliary || []).map(val => pick(val, ['id', 'categoryType', 'categoryId'])))
      }
    })
  });
}


const numChange = () => {
  let d = props.detail;
  let field = 'debitAmount';
  if (d.creditAmount || (!d.creditAmount && d.subject.balanceDirection === '贷')) {
    field = 'creditAmount';
  }
  props.detail[field] = round(multiply(d.num, d.price), 2)
}

defineExpose({
  doEdit,
  endEdit
})
</script>
<style scoped lang="less">
.v-table {

  &-td {
    &-subject {
      flex: 1;
      border-right: @border;
      font-weight: bold;
      position: relative;

      &-balance {
        position: absolute;
        bottom: 0;
        left: 8px;
        font-size: 12px;
      }

      &-unit-currency {
        position: absolute;
        bottom: 0;
        right: 0;
        padding: 5px 5px 0;
        font-weight: normal;
        z-index: 1;
        text-align: right;
      }

      &-dpc {
        display: block;
        height: 100%;

        :deep(.h-dropdowncustom-show) {
          height: 100%;
        }

        :deep(.h-dropdowncustom-show-content) {
          height: 100%;
          display: block;
        }
      }

      &-edit {
        resize: none;
        outline: none;
        height: 100%;
        width: 100%;
        overflow: hidden;
        font-size: 12px;
        padding: 8px;
        border: 1px solid @primary1-color;
      }

      &-list {
        font-size: 13px;

        &-content {
          height: 200px;
          overflow-y: auto;
          border-bottom: @border;

          li {
            padding: 4px 8px;
            cursor: pointer;

            &:hover {
              background-color: @gray3-color;
            }
          }
        }
      }

      &-text {
        position: relative;

        .addon {
          position: absolute;
          right: 0;
          top: 0;

          i {
            margin: 5px;
            font-size: 14px;
          }

          .fa-vcard {
            color: #ff6600;
          }

          .fa-money {
            color: @primary-color;
          }
        }
      }
    }
  }
}

.type-tabs {
  display: flex;
  border-bottom: @border;

  div {
    flex: 1;
    text-align: center;
    padding: 5px 0;

    &:hover {
      cursor: pointer;
      background-color: @primary-color;
      color: @white-color;
    }
  }

  .selected {
    background-color: @primary-color;
    color: @white-color;
  }
}

.subject-selected {
  background-color: @primary2-color;
}
</style>
